Skip to content

HubClient: retry transient Hub tree-listing failures (429/5xx)#2

Open
AurionRodgerDiablo wants to merge 1 commit into
john-rocky:mainfrom
AurionRodgerDiablo:fix/hub-tree-retry
Open

HubClient: retry transient Hub tree-listing failures (429/5xx)#2
AurionRodgerDiablo wants to merge 1 commit into
john-rocky:mainfrom
AurionRodgerDiablo:fix/hub-tree-retry

Conversation

@AurionRodgerDiablo

Copy link
Copy Markdown

Problem

HubClient.listFiles treats any non-200 response from the Hub tree API as variantNotFound, surfacing:

No '' variant in @ — this model may not be published for this platform.

…even when the subtree exists. In practice the Hub sheds load with transient 429 {"error":"maximum queue size reached"} (and occasional 5xx). Multi-bundle models list several subtrees (OCR resolves vision/decoder/assets/tokenizer) and those calls race, so a single 429 aborts the whole download with a misleading "not published" message.

Reproduced with mlboydaisuke/Unlimited-OCR-CoreAI via Examples/ReadDoc: hitting the tree API for the four subtrees returns 429 on some of them, and the run fails even though every subtree is present on main.

The large-file download path already retries 6×; only the tree-listing step did not.

Fix

Retry the tree listing up to 5× with exponential backoff (2/4/8/16 s) on 429/5xx. A firm 4xx (e.g. 404) still means the subtree really isn't published, so it keeps variantNotFound. Exhausting retries throws httpError(statusCode:) with the real status instead of the misleading message.

One file, Sources/CoreAIKitCore/HubClient.swift (+22/-3). No API or behavior change on the success path.

Verification

swift run readdoc-cli --model unlimited-ocr --image sample.png now completes (exit 0) through transient 429s and prints the document markdown.

https://claude.ai/code/session_01HyaY1ZCanqUvYbWVD4Rc53

listFiles treated any non-200 from the Hub tree API as variantNotFound,
surfacing "No '<path>' variant in <repo>@<rev> — this model may not be
published for this platform" even when the subtree exists. The Hub sheds
load with transient 429s ("maximum queue size reached") and occasional
5xx; a single 429 on any of a multi-bundle model's subtree listings (OCR
resolves vision/decoder/assets/tokenizer) failed the whole download with
a misleading message. The large-file download path already retried 6x;
only the tree listing did not.

Retry the listing up to 5x with exponential backoff (2/4/8/16s) on 429/5xx.
A firm 4xx (e.g. 404) still means the subtree really isn't published, so it
keeps variantNotFound. Exhausting retries throws httpError(statusCode:) with
the real code instead of the misleading "not published" message.

Reproduced and verified fixed with mlboydaisuke/Unlimited-OCR-CoreAI via
Examples/ReadDoc (swift run readdoc-cli --model unlimited-ocr).

Claude-Session: https://claude.ai/code/session_01HyaY1ZCanqUvYbWVD4Rc53
Copilot AI review requested due to automatic review settings July 21, 2026 17:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves robustness of Hugging Face Hub subtree listing by retrying transient Hub tree API failures, preventing misleading variantNotFound errors when the subtree exists but the API is temporarily shedding load.

Changes:

  • Add retry loop with exponential backoff for Hub tree listing requests.
  • Treat non-429 4xx responses as variantNotFound, but surface exhausted retries as httpError(statusCode:).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +43
if attempt > 0 {
try await Task.sleep(nanoseconds: UInt64(1 << attempt) * 1_000_000_000)
}
Comment on lines +55 to 57
guard status == 200 else {
throw CoreAIKitError.httpError(statusCode: status, file: api.absoluteString)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants